﻿(function () {
    var Engine = function (fieldId, nextFallingId, scoreId, levelId) {
        this.isPlaying = false;
        this.isGameOver = false;
        this.isAnimating = false;
        this.pressedKey = "";
        this.renderer = new tetris.Renderer(fieldId, nextFallingId, scoreId, levelId);
        this.colider = new tetris.CollisionDetector();
        this.factory = new tetris.Factory();

        this.rowsToDelete = [];
        var self = this;
        this.earth = new tetris.Earth(6, 9, function (index) {
            self.rowsToDelete.push(index);
        });
        this.falling = this.factory.createFallingObject
            (this.renderer._blockFallingCenterX, this.renderer._blockFallingCenterY);
        this.nextFalling = this.factory.createFallingObject
            (this.renderer._nextFallingCenter, this.renderer._nextFallingCenter);
        this.score = 0;
        this.level = 1;
        this.speed = 500;
    }
    Engine.prototype.pausePlay = function () {
        this.isPlaying = !this.isPlaying;
    };

    Engine.prototype.resolveCollisions = function (collisions) {
        if (collisions[tetris.CollisionType.Earth]) {
            this.earth.add(this.falling);
            this.earth.updateBodyAndReturnCollapsedRowsCount();

            this.nextFalling.moveTo
            (this.renderer._blockFallingCenterX, this.renderer._blockFallingCenterY);
            this.falling = this.nextFalling;

            this.nextFalling = this.factory.createFallingObject
            (this.renderer._nextFallingCenter, this.renderer._nextFallingCenter);

            while (this.rowsToDelete.length > 0) {
                var row = this.rowsToDelete.pop();
                this.renderer.eraseRowAnimation(row, 200, this);
                this.score += 10;
                //this.isAnimating = true;
                //while (this.isAnimating) {
                //    console.log("animating...");
                //}
            }

            this.renderer.render(this.falling, this.nextFalling, this.earth);
            this.renderer.renderScore(this.score);
            this.renderer.renderLevel(this.level);
        }
        else {
            this.renderer.renderFalling(this.falling);
        }
    };

    Engine.prototype._checkIfCollision = function (collisions) {
        var reverseBack = false;

        if (collisions[tetris.CollisionType.Earth]) {
            reverseBack = true;
        }

        if (collisions[tetris.CollisionType.TopEdge]) {
            reverseBack = true;
            this.isPlaying = false;
            this.isGameOver = true;
        }

        if (collisions[tetris.CollisionType.LeftEdge]) {
            reverseBack = true;
        }

        if (collisions[tetris.CollisionType.RightEdge]) {
            reverseBack = true;
        }

        return reverseBack;
    };
    Engine.prototype.getCollisionsFromAction = function (actionPressedKey) {
        var collisions = {};
        var reverse = false;

        switch (actionPressedKey) {
            case "38": //Up
                this.falling.rotate();
                collisions = this.colider.getCollisions(this.falling, this.earth);
                reverse = this._checkIfCollision(collisions);
                if (reverse) {
                    this.falling.rotateBack();
                }
                break;
            case "37": //Left
                this.falling.moveLeft();
                collisions = this.colider.getCollisions(this.falling, this.earth);
                reverse = this._checkIfCollision(collisions);
                if (reverse) {
                    this.falling.moveRight();
                }
                break;
            case "39": //Right
                this.falling.moveRight();
                collisions = this.colider.getCollisions(this.falling, this.earth);
                reverse = this._checkIfCollision(collisions);
                if (reverse) {
                    this.falling.moveLeft();
                }
                break;
            case "40": //Down
                this.falling.moveDown();
                collisions = this.colider.getCollisions(this.falling, this.earth);
                reverse = this._checkIfCollision(collisions);
                if (reverse) {
                    this.falling.moveUp();
                }
                break;
        }

        return collisions;
    };
    Engine.prototype.playCycleTurn = function () {
        var self = this;

        if (this.isGameOver) {
            var name = prompt("Please enter your name!");
            highScore.saveScore(name, this.score);
            $("#game").hide().load("home.html", function (response, status, xhr) {
                if (status === "error") {
                    // handle error 
                }
                else {
                    $(this).fadeIn();
                }
            });
            return;
        }

        if (this.isPlaying) {
            try{
                var collisions;

                if (this.pressedKey != "") {
                    collisions = this.getCollisionsFromAction(this.pressedKey);
                    this.resolveCollisions(collisions);
                }
                collisions = this.getCollisionsFromAction("40"); //keyDown for moving downwards
                this.resolveCollisions(collisions);

                this.pressedKey = "";
                setTimeout(function () { self.playCycleTurn(); }, this.speed);
            }
            catch (e) {
                this.isGameOver = true;
                setTimeout(function () { self.playCycleTurn(); }, this.speed);
            }
        }
    }; 
   

    Engine.prototype.start = function () {
        var self = this;
        this.isPlaying = true;

        window.onkeydown = function (ev) {
            self.pressedKey = ev.keyCode.toString();
        };

        this.renderer.render(this.falling, this.nextFalling, this.earth);
        this.playCycleTurn();
    };

    tetris.Engine = Engine;
})();